package com.huohuzhihui.merchant.service.impl;

import com.alibaba.fastjson.JSON;
import com.huohuzhihui.common.core.domain.entity.SysDept;
import com.huohuzhihui.common.exception.CustomException;
import com.huohuzhihui.common.utils.DateUtils;
import com.huohuzhihui.common.utils.uuid.IdUtils;
import com.huohuzhihui.merchant.domain.Goods;
import com.huohuzhihui.merchant.domain.Order;
import com.huohuzhihui.merchant.domain.OrderDetail;
import com.huohuzhihui.merchant.mapper.GoodsMapper;
import com.huohuzhihui.merchant.service.IGoodsService;
import com.huohuzhihui.merchant.service.IOrderDetailService;
import com.huohuzhihui.merchant.service.IOrderService;
import com.huohuzhihui.merchant.service.IPayService;
import com.huohuzhihui.system.service.ISysDeptService;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfig;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 套餐商品Service业务层处理
 *
 * @author huohuzhihui
 * @date 2021-06-01
 */
@Service
public class PayServiceImpl implements IPayService {
    @Autowired
    private IOrderService orderService;
    @Autowired
    private IOrderDetailService orderDetailService;
    @Autowired
    private ISysDeptService sysDeptService;
    @Autowired
    private IGoodsService goodsService;

    @Value("${wxpay.appId}")
    private String appId;

    @Value("${wxpay.appSecret}")
    private String appSecret;

    @Value("${wxpay.certPath}")
    private String certPath;

    @Value("${wxpay.domain}")
    private String domain;

    @Value("${wxpay.mchId}")
    private String mchId;

    @Value("${wxpay.partnerKey}")
    private String partnerKey;
    @Value("${wxpay.notifyUrl}")
    private String notifyUrl;
    @Value("${wxpay.refundNotifyUrl}")
    private String refundNotifyUrl;

    private WxPayApiConfig wxPayApiConfig;

    @PostConstruct
    public WxPayApiConfig getApiConfig() {
        wxPayApiConfig = WxPayApiConfig.builder()
                .appId(appId)
                .mchId(mchId)
                .partnerKey(partnerKey)
                .certPath(certPath)
                .domain(domain)
                .build();
        return wxPayApiConfig;
    }


    @Override
    public String prepare(Long orderId, String openId, String ip) {
        Order order = orderService.selectOrderById(orderId);
        String tradeNo = IdUtils.fastSimpleUUID();

        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderId(order.getId());
        List<OrderDetail> orderDetailList = orderDetailService.selectOrderDetailList(orderDetail);
        for (int i = 0; i < orderDetailList.size(); i++) {
            OrderDetail detail = orderDetailList.get(i);
            detail.setOutTradeNo(tradeNo);
            this.orderDetailService.insertOrderDetail(detail);
        }

        String subject = "云豆购买";
        String body = "云豆购买";
        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(body)
                .attach(subject)
                .out_trade_no(tradeNo)
                .total_fee(order.getAmount().multiply(new BigDecimal("100")).stripTrailingZeros().toPlainString())
                .spbill_create_ip(ip)
                .notify_url(notifyUrl)
                .trade_type(TradeType.JSAPI.getTradeType())
                .openid(openId)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.pushOrder(false, params);

        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            throw new CustomException(returnMsg, 500);
        }
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            throw new CustomException(returnMsg, 500);
        }
        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
        String prepayId = result.get("prepay_id");
        Map<String, String> packageParams = WxPayKit.miniAppPrepayIdCreateSign(wxPayApiConfig.getAppId(), prepayId,
                wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
        String jsonStr = JSON.toJSONString(packageParams);
        System.out.println("支付参数为------------------" + jsonStr);
        return jsonStr;
    }

    @Override
    public String notify(HttpServletRequest request) {
        String xmlMsg = HttpKit.readData(request);
        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
        String returnCode = params.get("return_code");

        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 注意此处签名方式需与统一下单的签名类型一致
        if (WxPayKit.verifyNotify(params, partnerKey, SignType.HMACSHA256)) {
            if (WxPayKit.codeIsOk(returnCode)) {
                String tradeNo = params.get("out_trade_no");
                // 更新订单信息
                OrderDetail orderDetail = new OrderDetail();
                orderDetail.setOutTradeNo(tradeNo);

                List<OrderDetail> orderDetailList = this.orderDetailService.selectOrderDetailList(orderDetail);
                for (int i = 0; i < orderDetailList.size(); i++) {
                    OrderDetail detail = orderDetailList.get(i);
                    if (detail.getStatus() == 0) {//待支付
                        detail.setStatus(1);//支付成功
                        detail.setUpdateTime(DateUtils.getNowDate());
                        detail.setUpdateBy("系统");
                        orderDetailService.updateOrderDetail(detail);

                        //更新订单状态
                        long orderId = detail.getOrderId();
                        Order order = this.orderService.selectOrderById(orderId);
                        order.setStatus(1);//支付成功
                        order.setUpdateTime(DateUtils.getNowDate());
                        order.setUpdateBy("系统");
                        orderService.updateOrder(order);

                        //更新余额
                        //更新当前账户余额
                        Goods goods = goodsService.selectGoodsById(detail.getGoodsId());
                        sysDeptService.rechargeVideoCount(order.getMerchantId(), goods.getVideoCount());
                    }
                }
            }
        }
        // 发送通知等
        Map<String, String> xml = new HashMap<String, String>(2);
        xml.put("return_code", "SUCCESS");
        xml.put("return_msg", "OK");
        return WxPayKit.toXml(xml);
    }
}
